package Test;

import static org.junit.Assert.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;

import org.junit.Before;
import org.junit.Test;

import Error.ScriptError;
import Script.JScriptReader;
import interfaces.ErrorReport;
import interfaces.ScriptReader;
import interfaces.TextScriptArea;

public class JScriptReaderTest {
	private String newline;
	private String charset;
	
	@Before
	public void setup() {
		newline = System.getProperty("line.separator");
		charset = "ISO-8859-1";
	}
	
	/* Check textarea generation. */
	
	@Test
	public void readerCanDiscardSingleBeginScript() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script1.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<TextScriptArea> ta = tr.read(0);
		TextScriptArea area = ta.get(0);
		
		assertEquals(area.getText(), "Opening text.<LINE>" + newline);
	}
	
	@Test
	public void readerCanDiscardMultipleBeginScript() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script3.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<TextScriptArea> ta = tr.read(0);
		TextScriptArea area = ta.get(0);
		
		assertEquals(area.getText(), "Opening text 2.<LINE>" + newline);
	}
	
	@Test
	public void readerCanDumpSinglePointerToText() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script1.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<TextScriptArea> ta = tr.read(0);
		TextScriptArea area1 = ta.get(1);
		TextScriptArea area2 = ta.get(2);
		ArrayList<Integer> p1 = area1.getPointers();
		ArrayList<Integer> p2 = area2.getPointers();
		
		assertEquals(p1.get(0), new Integer(1));
		assertEquals(p2.get(0), new Integer(2));
	}
	
	@Test
	public void readerCanDumpMultiplePointersToText() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script2.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<TextScriptArea> ta = tr.read(0);
		TextScriptArea area = ta.get(1);
		ArrayList<Integer> p = area.getPointers();
		
		assertEquals(p.get(0), new Integer(2));
		assertEquals(p.get(1), new Integer(3));
		assertEquals(p.get(2), new Integer(4));
	}
	
	@Test
	public void readerCanFindPointerLastInFileWithEmptyString() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script1.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<TextScriptArea> ta = tr.read(0);
		TextScriptArea area = ta.get(3);
		ArrayList<Integer> p = area.getPointers();
		
		assertEquals(area.getText(), "");
		assertEquals(p.get(0), new Integer(3));
	}
	
	@Test
	public void readerCanReadText() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script1.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<TextScriptArea> ta = tr.read(0);
		
		assertEquals(ta.get(0).getText(), "Opening text.<LINE>" + newline);
		assertEquals(ta.get(1).getText(), "Text block 1<END>" + newline);
		assertEquals(ta.get(2).getText(), "Text block 2<LINE>" + newline 
											+ "Some more text.<LINE>" + newline
											+ "<END>" + newline);
	}
	
	/* Script validation, pointer duplicates. */
	
	@Test
	public void invalidatesDuplicatePointer() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script4.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<ErrorReport> errors = tr.isValid();
		
		/* Pointer 1 has a duplicate on line 8. */
		ScriptError error = (ScriptError) errors.get(0);
		
		assertEquals(error.getLine(), 8);
	}
	
	@Test
	public void invalidatesDuplicatePointersWithoutZeros() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script4.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<ErrorReport> errors = tr.isValid();

		/* Pointer 6 has a duplicate on line 12. */
		ScriptError error = (ScriptError) errors.get(5);
		
		assertEquals(error.getLine(), 12);
		
	}
	
	@Test
	public void invalidatesDuplicatePointersWithTrailingZeros() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script4.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<ErrorReport> errors = tr.isValid();

		/* Pointer 6 has a duplicate on line 12. */
		ScriptError error = (ScriptError) errors.get(4);
		
		assertEquals(error.getLine(), 15);
		
	}
	
	@Test
	public void invalidatesPointersWithTooManyNumbers() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script4.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<ErrorReport> errors = tr.isValid();

		/* Pointer 6 has a duplicate on line 12. */
		ScriptError error = (ScriptError) errors.get(6);

		assertEquals(error.getLine(), 14);
		
	}
	
	@Test
	public void invalidatesPointerWithTooHighPointerNumber() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script10.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		ArrayList<ErrorReport> errors = tr.isValid();

		/* Only one error is present. */
		assertEquals(errors.size(), 1);
		
		/* A pointer has too high number on line 2. */
		ScriptError error = (ScriptError) errors.get(0);
		assertEquals(error.getLine(), 2);
	}
	
	@Test
	/**
	 * Script has pointer 1 to 5.
	 */
	public void canFindTheHighestPointerNumber() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script2.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		tr.read(0);
		
		assertEquals(tr.getNumberOfPointers(), 5);
	}
	
	@Test
	/**
	 * Script 3 has pointer 1 and 3.
	 */
	public void canFindHighestPointerWhenTheresPointerValueGaps() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script3.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		tr.read(0);
		
		assertEquals(tr.getNumberOfPointers(), 3);
	}
	
	@Test
	public void canReadPointerNumbersUpToMaxIntegerLimit() throws FileNotFoundException {
		File textFile = new File("testFiles/testScripts/Script9.txt");
		ScriptReader tr = new JScriptReader(textFile, charset);
		tr.read(0);
		
		assertEquals(tr.getNumberOfPointers(), 2147483647);
	}
	
	/**
	 * Fixed length testing here-
	 * 
	 * 	- Gives null with pointer strings
	 * 	- Skips last string if no end tag present
	 * 	- Cuts long strings
	 * 	- Inserts an empty string (all padding) if there's an end tag first i the script.
	 */
	
	@Test
	public void givesNullReturnIfScriptHasPointerInIt() throws FileNotFoundException {
		File script = new File("testFiles/testScripts/Script1.txt");
		ScriptReader r = new JScriptReader(script, "ISO-8859-1");
		ArrayList<TextScriptArea> text = r.read(10);
		assertEquals(null, text);
	}
	
	@Test
	public void skipsLastStringIfNoEndTagPresent() throws FileNotFoundException {
		File script = new File("testFiles/testScripts/Script14.txt");
		ScriptReader r = new JScriptReader(script, "ISO-8859-1");
		ArrayList<TextScriptArea> text = r.read(10);
		assertEquals(8, text.size());
	}
	
	@Test
	public void cutsLongStrings() throws FileNotFoundException {
		File script = new File("testFiles/testScripts/Script14.txt");
		ScriptReader r = new JScriptReader(script, "ISO-8859-1");
		ArrayList<TextScriptArea> text = r.read(10);
		String t;
		
		for (TextScriptArea a : text) {
			t = a.getText();
			
			assertTrue(t.length() <= 10);
		}
	}
	
	@Test
	public void insertsEmptyStringIfFirstTextIsEndTag() throws FileNotFoundException {
		File script = new File("testFiles/testScripts/Script14.txt");
		ScriptReader r = new JScriptReader(script, "ISO-8859-1");
		ArrayList<TextScriptArea> text = r.read(10);
		assertEquals("", text.get(0).getText());
	}
	
	@Test
	public void givesEmptyListIfThereAreNoEndTags() throws FileNotFoundException {
		File script = new File("testFiles/testScripts/Script5.txt");
		ScriptReader r = new JScriptReader(script, "ISO-8859-1");
		ArrayList<TextScriptArea> text = r.read(10);
		assertTrue(text.size() == 0);
	}
	
	

}
